package cn.com.easy.pay.alipay.www.controller;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.com.easy.exception.BusinessException;
import cn.com.easy.pay.alipay.www.config.AlipayConfig;
import cn.com.easy.pay.alipay.www.util.AlipayNotify;

/**
 * 阿里支付宝，页面跳转同步，基本控制器(spring mvc)
 * 
 * @author nibili 2017年4月1日
 * 
 */
public abstract class AlipayReturnBaseController {

	private Logger logger = LoggerFactory.getLogger(AlipayReturnBaseController.class);

	/**
	 * spring mvc跳转的jsp页面
	 * 
	 * @param modelMap
	 * @param request
	 * @param response
	 * @param redirectAttributes
	 * @param returnParam
	 * @return
	 * @author nibili 2017年4月1日
	 */
	public abstract String successReturnPagePath(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes,
			ReturnParam returnParam);

	/**
	 * 
	 * 异常跳转的页面<br/>
	 * 如果发生异常，请自行 查看 trade_status 的值 ，做相应处理,一般都是正确了才会跳到这个页面<br/>
	 * 如果发生异常加调这个方法前，会把错误信息放到 errorMsg中 modelMap.put("errorMsg",
	 * ex.getMessage());
	 * 
	 * @param modelMap
	 * @param request
	 * @param response
	 * @param redirectAttributes
	 * @param returnParam
	 * @return
	 * @author nibili 2017年4月1日
	 */
	public abstract String errorReturnPagePath(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes,
			ReturnParam returnParam);

	/**
	 * 阿里配置参数
	 * 
	 * @return
	 * @author nibili 2017年4月1日
	 */
	public abstract AlipayConfig getAlipayConfig();

	/**
	 * 
	 * @param modelMap
	 * @param request
	 * @param response
	 * @param redirectAttributes
	 * @param returnParam
	 * @return
	 * @author nibili 2017年4月1日
	 * @throws BusinessException
	 */
	@RequestMapping("/return")
	public String returnPage(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes, ReturnParam returnParam)
			throws BusinessException {
		try {
			// 获取支付宝POST过来反馈信息
			Map<String, String> params = new HashMap<String, String>();
			Map<String, String[]> requestParams = request.getParameterMap();
			for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				String[] values = (String[]) requestParams.get(name);
				String valueStr = "";
				for (int i = 0; i < values.length; i++) {
					valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
				}
				// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
				// valueStr = new String(valueStr.getBytes("ISO-8859-1"),
				// "gbk");
				params.put(name, valueStr);
			}

			// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//

			// 计算得出通知验证结果
			boolean verify_result = AlipayNotify.verify(params, getAlipayConfig());
			if (verify_result) {// 验证成功
				// ////////////////////////////////////////////////////////////////////////////////////////
				// 请在这里加上商户的业务逻辑程序代码

				// ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
				if (StringUtils.equals(returnParam.getTrade_status(), "TRADE_FINISHED") == true || StringUtils.equals(returnParam.getTrade_status(), "TRADE_SUCCESS") == true) {
					// 判断该笔订单是否在商户网站中已经做过处理
					// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					// 如果有做过处理，不执行商户的业务程序
					return successReturnPagePath(modelMap, request, response, redirectAttributes, returnParam);
				} else {
					modelMap.put("errorMsg", "支付异常");
					return errorReturnPagePath(modelMap, request, response, redirectAttributes, returnParam);
				}

				// 该页面可做页面美工编辑
				// response.getOutputStream().println("验证成功<br />");
				// ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

				// ////////////////////////////////////////////////////////////////////////////////////////
			} else {
				// 该页面可做页面美工编辑
				throw new BusinessException("验证失败");
			}
		} catch (BusinessException ex) {
			logger.info("支付宝return业务代码异常", ex);
			modelMap.put("errorMsg", ex.getMessage());
			return errorReturnPagePath(modelMap, request, response, redirectAttributes, returnParam);
		} catch (Exception ex) {
			logger.info("支付宝return异常", ex);
			modelMap.put("errorMsg", "支付异常");
			return errorReturnPagePath(modelMap, request, response, redirectAttributes, returnParam);
		}

	}

	/**
	 * 支付宝返回时带的参数
	 * 
	 * @author nibili 2017年4月1日
	 * 
	 */
	public static class ReturnParam {
		/** 成功标识 */
		private String is_success;
		/** 签名方式 */
		private String sign_type;
		/** 签名 */
		private String sign;
		/** 商户网站唯一订单号 */
		private String out_trade_no;
		/** 商品名称 */
		private String subject;
		/** 支付类型 */
		private String payment_type;
		/** 接口名称 */
		private String exterface;
		/** 支付宝交易号 */
		private String trade_no;
		/** 交易状态 */
		private String trade_status;
		/** 通知校验ID */
		private String notify_id;
		/** 通知时间 */
		private String notify_time;
		/** 通知类型 */
		private String notify_type;
		/** 卖家支付宝账号 */
		private String seller_email;
		/** 买家支付宝账号 */
		private String buyer_email;
		/** 卖家支付宝账户号 */
		private String seller_id;
		/** 买家支付宝账户号 */
		private String buyer_id;
		/** 交易金额 */
		private String total_fee;
		/** 商品描述 */
		private String body;
		/** 公用回传参数 */
		private String extra_common_param;

		/**
		 * get 成功标识
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getIs_success() {
			return is_success;
		}

		/**
		 * set 成功标识
		 * 
		 * @param is_success
		 * @author nibili 2017年4月1日
		 */
		public void setIs_success(String is_success) {
			this.is_success = is_success;
		}

		/**
		 * get 签名方式
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSign_type() {
			return sign_type;
		}

		/**
		 * set 签名方式
		 * 
		 * @param sign_type
		 * @author nibili 2017年4月1日
		 */
		public void setSign_type(String sign_type) {
			this.sign_type = sign_type;
		}

		/**
		 * get 签名
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSign() {
			return sign;
		}

		/**
		 * set 签名
		 * 
		 * @param sign
		 * @author nibili 2017年4月1日
		 */
		public void setSign(String sign) {
			this.sign = sign;
		}

		/**
		 * get 商户网站唯一订单号
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getOut_trade_no() {
			return out_trade_no;
		}

		/**
		 * set 商户网站唯一订单号
		 * 
		 * @param out_trade_no
		 * @author nibili 2017年4月1日
		 */
		public void setOut_trade_no(String out_trade_no) {
			this.out_trade_no = out_trade_no;
		}

		/**
		 * get 商品名称
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSubject() {
			return subject;
		}

		/**
		 * set 商品名称
		 * 
		 * @param subject
		 * @author nibili 2017年4月1日
		 */
		public void setSubject(String subject) {
			this.subject = subject;
		}

		/**
		 * get 支付类型
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getPayment_type() {
			return payment_type;
		}

		/**
		 * set 支付类型
		 * 
		 * @param payment_type
		 * @author nibili 2017年4月1日
		 */
		public void setPayment_type(String payment_type) {
			this.payment_type = payment_type;
		}

		/**
		 * get 接口名称
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getExterface() {
			return exterface;
		}

		/**
		 * set 接口名称
		 * 
		 * @param exterface
		 * @author nibili 2017年4月1日
		 */
		public void setExterface(String exterface) {
			this.exterface = exterface;
		}

		/**
		 * get 支付宝交易号
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getTrade_no() {
			return trade_no;
		}

		/**
		 * set 支付宝交易号
		 * 
		 * @param trade_no
		 * @author nibili 2017年4月1日
		 */
		public void setTrade_no(String trade_no) {
			this.trade_no = trade_no;
		}

		/**
		 * get 交易状态
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getTrade_status() {
			return trade_status;
		}

		/**
		 * set 交易状态
		 * 
		 * @param trade_status
		 * @author nibili 2017年4月1日
		 */
		public void setTrade_status(String trade_status) {
			this.trade_status = trade_status;
		}

		/**
		 * get 通知校验ID
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getNotify_id() {
			return notify_id;
		}

		/**
		 * set 通知校验ID
		 * 
		 * @param notify_id
		 * @author nibili 2017年4月1日
		 */
		public void setNotify_id(String notify_id) {
			this.notify_id = notify_id;
		}

		/**
		 * get 通知时间
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getNotify_time() {
			return notify_time;
		}

		/**
		 * set 通知时间
		 * 
		 * @param notify_time
		 * @author nibili 2017年4月1日
		 */
		public void setNotify_time(String notify_time) {
			this.notify_time = notify_time;
		}

		/**
		 * get 通知类型
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getNotify_type() {
			return notify_type;
		}

		/**
		 * set 通知类型
		 * 
		 * @param notify_type
		 * @author nibili 2017年4月1日
		 */
		public void setNotify_type(String notify_type) {
			this.notify_type = notify_type;
		}

		/**
		 * get 卖家支付宝账号
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSeller_email() {
			return seller_email;
		}

		/**
		 * set 卖家支付宝账号
		 * 
		 * @param seller_email
		 * @author nibili 2017年4月1日
		 */
		public void setSeller_email(String seller_email) {
			this.seller_email = seller_email;
		}

		/**
		 * get 买家支付宝账号
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getBuyer_email() {
			return buyer_email;
		}

		/**
		 * set 买家支付宝账号
		 * 
		 * @param buyer_email
		 * @author nibili 2017年4月1日
		 */
		public void setBuyer_email(String buyer_email) {
			this.buyer_email = buyer_email;
		}

		/**
		 * get 卖家支付宝账户号
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getSeller_id() {
			return seller_id;
		}

		/**
		 * set 卖家支付宝账户号
		 * 
		 * @param seller_id
		 * @author nibili 2017年4月1日
		 */
		public void setSeller_id(String seller_id) {
			this.seller_id = seller_id;
		}

		/**
		 * get 买家支付宝账户号
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getBuyer_id() {
			return buyer_id;
		}

		/**
		 * set 买家支付宝账户号
		 * 
		 * @param buyer_id
		 * @author nibili 2017年4月1日
		 */
		public void setBuyer_id(String buyer_id) {
			this.buyer_id = buyer_id;
		}

		/**
		 * get 交易金额
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getTotal_fee() {
			return total_fee;
		}

		/**
		 * set 交易金额
		 * 
		 * @param total_fee
		 * @author nibili 2017年4月1日
		 */
		public void setTotal_fee(String total_fee) {
			this.total_fee = total_fee;
		}

		/**
		 * get 商品描述
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getBody() {
			return body;
		}

		/**
		 * set 商品描述
		 * 
		 * @param body
		 * @author nibili 2017年4月1日
		 */
		public void setBody(String body) {
			this.body = body;
		}

		/**
		 * get 公用回传参数
		 * 
		 * @return
		 * @author nibili 2017年4月1日
		 */
		public String getExtra_common_param() {
			return extra_common_param;
		}

		/**
		 * set 公用回传参数
		 * 
		 * @param extra_common_param
		 * @author nibili 2017年4月1日
		 */
		public void setExtra_common_param(String extra_common_param) {
			this.extra_common_param = extra_common_param;
		}

	}
}
